package com.kizuki.aop;

import com.google.gson.Gson;
import com.kizuki.annotaion.WebLog;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
 * 高版本顺序：around(start)-> before -> 调用 -> afterReturning -> after -> around(end)
 * =======================Around Start=========================
 * ==========================Before===========================
 * url                :/h
 * desc               :hello world请求
 * http method        :GET
 * class method       :com.kizuki.controller.MyAopController.helloWorld
 * ip                 :0:0:0:0:0:0:0:1
 * request args       :[]
 * 真正的调用：Print Hello World!
 * =======================AfterReturning=======================
 * ===========================After============================
 * Response Args :"Hello World!"
 * Time-Consuming :6ms
 * ========================Around End==========================
 */
@Slf4j
@Aspect
@Component
public class WebLogAspect {

    @Pointcut("@annotation(com.kizuki.annotaion.WebLog)")
    public void WebLog() {

    }

    @Before("WebLog()")
    public void beforeNotify(JoinPoint joinPoint) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        String desc = ((MethodSignature) joinPoint.getSignature()).getMethod().getAnnotation(WebLog.class).desc();
        log.info("==========================Before===========================");
        log.info("url                :{}", request.getRequestURI());
        log.info("desc               :{}", desc);
        log.info("http method        :{}", request.getMethod());
        log.info("class method       :{}.{}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
        log.info("ip                 :{}", request.getRemoteAddr());
        log.info("request args       :{}", new Gson().toJson(joinPoint.getArgs()));
    }

    @After("WebLog()")
    public void afterNotify() {
        log.info("===========================After============================");
    }

    @AfterReturning("WebLog()")
    public void afterReturningNotify() {
        log.info("=======================AfterReturning=======================");
    }

    @AfterThrowing("WebLog()")
    public void afterThrowingNotify() {
        log.info("=======================AfterThrowing====================+===");
    }

    @Around("WebLog()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        log.info("=======================Around Start=========================");
        long startTime = System.currentTimeMillis();
        Object retVal = proceedingJoinPoint.proceed();
        log.info("Response Args :{}", new Gson().toJson(retVal));
        log.info("Time-Consuming :{}ms", System.currentTimeMillis() - startTime);
        log.info("========================Around End==========================");
        return retVal;
    }

}
